<?php

namespace fastphp;

use fastphp\util\File;

/**
 * 请求处理类
 * 负责获取和处理HTTP请求信息，符合MVC架构中的请求处理层
 */
class Request
{
    /**
     * 判断是否为GET请求
     * @return bool
     */
    public function isGet(): bool
    {
        return $_SERVER['REQUEST_METHOD'] == 'GET';
    }

    /**
     * 判断是否为POST请求
     * @return bool
     */
    public function isPost(): bool
    {
        return $_SERVER['REQUEST_METHOD'] == 'POST';
    }

    /**
     * 判断是否为DELETE请求
     * @return bool
     */
    public function isDelete(): bool
    {
        return $_SERVER['REQUEST_METHOD'] == 'DELETE';
    }

    /**
     * 判断是否为PUT请求
     * @return bool
     */
    public function isPut(): bool
    {
        return $_SERVER['REQUEST_METHOD'] == 'PUT';
    }
    
    /**
     * 判断是否为AJAX请求
     * @return bool
     */
    public function isAjax(): bool
    {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 
               strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
    }

    /**
     * 获取GET参数
     * @param string|null $name 参数名
     * @param mixed $default 默认值
     * @return mixed
     */
    public function get($name = null, $default = null)
    {
        if ($name === null) {
            return $this->sanitizeData($_GET);
        }
        return isset($_GET[$name]) ? $this->sanitizeData($_GET[$name]) : $default;
    }

    /**
     * 获取POST参数
     * @param string|null $name 参数名
     * @param mixed $default 默认值
     * @return mixed
     */
    public function post($name = null, $default = null)
    {
        // 尝试解析JSON数据
        $jsonData = $this->parseJsonInput();
        if ($jsonData !== null) {
            if ($name === null) {
                return $this->sanitizeData($jsonData);
            }
            return isset($jsonData[$name]) ? $this->sanitizeData($jsonData[$name]) : $default;
        }
        
        // 回退到$_POST
        if ($name === null) {
            return $this->sanitizeData($_POST);
        }
        return isset($_POST[$name]) ? $this->sanitizeData($_POST[$name]) : $default;
    }

    /**
     * 获取PUT参数
     * @param string|null $name 参数名
     * @param mixed $default 默认值
     * @return mixed
     */
    public function put($name = null, $default = null)
    {
        $data = $this->parseJsonInput();
        if ($data === null) {
            // 尝试解析表单格式的PUT数据
            parse_str(file_get_contents('php://input'), $data);
        }
        
        if ($name === null) {
            return $this->sanitizeData($data);
        }
        return isset($data[$name]) ? $this->sanitizeData($data[$name]) : $default;
    }

    /**
     * 获取DELETE参数
     * @param string|null $name 参数名
     * @param mixed $default 默认值
     * @return mixed
     */
    public function delete($name = null, $default = null)
    {
        $data = $this->parseJsonInput();
        if ($data === null) {
            // 尝试解析表单格式的DELETE数据
            parse_str(file_get_contents('php://input'), $data);
        }
        
        if ($name === null) {
            return $this->sanitizeData($data);
        }
        return isset($data[$name]) ? $this->sanitizeData($data[$name]) : $default;
    }

    /**
     * 获取上传的文件
     * @param string|null $name 文件名
     * @return File|null
     */
    public function file($name = null)
    {
        if ($name === null) {
            return null;
        }
        return isset($_FILES[$name]) ? new File($_FILES[$name]) : null;
    }

    /**
     * 获取请求参数（自动适配请求方法）
     * @param string|null $name 参数名
     * @param mixed $default 默认值
     * @return mixed
     */
    public function param($name = null, $default = null)
    {
        // 根据不同的请求方法获取参数
        if ($this->isPost()) {
            return $this->post($name, $default);
        } elseif ($this->isPut()) {
            return $this->put($name, $default);
        } elseif ($this->isDelete()) {
            return $this->delete($name, $default);
        } else {
            // 默认为GET
            return $this->get($name, $default);
        }
    }
    
    /**
     * 获取请求URI
     * @return string
     */
    public function getUri(): string
    {
        return $_SERVER['REQUEST_URI'] ?? '';
    }
    
    /**
     * 获取请求路径（不包含查询字符串）
     * @return string
     */
    public function getPath(): string
    {
        $uri = $this->getUri();
        $pos = strpos($uri, '?');
        return $pos !== false ? substr($uri, 0, $pos) : $uri;
    }
    
    /**
     * 获取请求头信息
     * @param string|null $name 头信息名称
     * @return array|string|null
     */
    public function header($name = null)
    {
        $headers = getallheaders();
        if ($name === null) {
            return $headers;
        }
        
        $name = strtolower($name);
        foreach ($headers as $key => $value) {
            if (strtolower($key) == $name) {
                return $value;
            }
        }
        return null;
    }
    
    /**
     * 获取客户端IP地址
     * @return string
     */
    public function getClientIp(): string
    {
        $ip = $_SERVER['REMOTE_ADDR'] ?? '';
        
        // 处理代理IP
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $ip = trim($ips[0]);
        } elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }
        
        return $ip;
    }
    
    /**
     * 解析JSON格式的请求体
     * @return array|null 解析成功返回数组，失败返回null
     */
    private function parseJsonInput()
    {
        $json = file_get_contents('php://input');
        if (empty($json)) {
            return null;
        }
        
        $data = json_decode($json, true);
        return json_last_error() === JSON_ERROR_NONE ? $data : null;
    }
    
    /**
     * 对输入数据进行安全过滤
     * @param mixed $data 需要过滤的数据
     * @return mixed 过滤后的数据
     */
    private function sanitizeData($data)
    {
        if (is_array($data)) {
            return array_map([$this, 'sanitizeData'], $data);
        } elseif (is_string($data)) {
            // 基本的HTML实体编码，防止XSS攻击
            return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
        }
        return $data;
    }

    public function getMethod(): string
    {
        return $_SERVER['REQUEST_METHOD'] ?? 'GET';
    }
    
    private $attributes = [];
    
    /**
     * 设置自定义属性
     * @param string $key
     * @param mixed $value
     */
    public function setAttribute(string $key, $value): void
    {
        $this->attributes[$key] = $value;
    }
    
    /**
     * 获取自定义属性
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    public function getAttribute(string $key, $default = null)
    {
        return $this->attributes[$key] ?? $default;
    }
}